package org.rhok.pdx.ncn.application;

import java.util.List;

import org.rhok.pdx.ncn.R;
import org.rhok.pdx.ncn.background.MapPlotterTask;
import org.rhok.pdx.ncn.background.ServerSyncerTask;
import org.rhok.pdx.ncn.background.TrackingLocationListener;
import org.rhok.pdx.ncn.background.TrackingPhoneStateListener;
import org.rhok.pdx.ncn.background.WifiSignalTrackerTask;
import org.rhok.pdx.ncn.common.Utils;

import android.content.Context;
import android.location.LocationListener;
import android.location.LocationManager;
import android.net.wifi.WifiManager;
import android.os.Bundle;
import android.telephony.PhoneStateListener;
import android.telephony.TelephonyManager;
import android.view.KeyEvent;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.widget.EditText;
import android.widget.ImageButton;
import android.widget.LinearLayout;

import com.google.android.maps.GeoPoint;
import com.google.android.maps.MapActivity;
import com.google.android.maps.MapController;
import com.google.android.maps.MapView;
import com.google.android.maps.MyLocationOverlay;
import com.google.android.maps.Overlay;

public class NCNMainActivity extends MapActivity {
	
	private ApplicationContext context;
	
	private EditText gpsText;
	private EditText signalText;
	private EditText wifiText;
	private ImageButton zoomToBtn;
	private LinearLayout dataView;
	
	private MapController mapController;
	private MapView mapView;
	private MyLocationOverlay locOverlay;
	
    private LocationListener locListener;
    private PhoneStateListener psListener;
    
    private MapPlotterTask mapPlotter;
    private ServerSyncerTask serverSyncer;
    private WifiSignalTrackerTask wifiTracker;
    
    private LocationManager locManager;
    private TelephonyManager teleManager;
    private WifiManager wifiManager;

	private List<Overlay> overlays;
	
	@Override
	public void onCreate(Bundle savedInstanceStage) {
		super.onCreate(savedInstanceStage);
		setContentView(R.layout.map_layout);
		
		context = new ApplicationContext(this);
		getViews();
		getSystemServices();
		
		setupMap();
		setupBackgroundProcesses();
	}
	
	private void getViews() {
		gpsText = (EditText) findViewById(R.id.value_gps);
		signalText = (EditText) findViewById(R.id.value_signal);
		wifiText = (EditText) findViewById(R.id.value_wifi);
		
		mapView = (MapView) findViewById(R.id.map_view);
		dataView = (LinearLayout) findViewById(R.id.data_view);
		zoomToBtn = (ImageButton) findViewById(R.id.my_loc_button);
		zoomToBtn.setImageResource(android.R.drawable.ic_menu_mylocation);
		
		context.mapView(mapView);
	}
	
	private void getSystemServices() {
		locListener = new TrackingLocationListener(context, gpsText);
        psListener = new TrackingPhoneStateListener(context, signalText);
        
        locManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
        teleManager = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
        wifiManager = (WifiManager) getSystemService(Context.WIFI_SERVICE);
	}
	
	@Override
	protected boolean isRouteDisplayed() {
		return false;
	}
	
    /* (non-Javadoc)
     * @see android.app.Activity#onCreateOptionsMenu(android.view.Menu)
     */
    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        MenuInflater inflater = getMenuInflater();
        inflater.inflate(R.menu.menu, menu);
        return true;
    }

    /* (non-Javadoc)
     * @see android.app.Activity#onOptionsItemSelected(android.view.MenuItem)
     */
    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle item selection
        switch (item.getItemId()) {
        case R.id.menu:
            swapViews(item);
            return true;
        default:
            return super.onOptionsItemSelected(item);
        }
    }
	
	private void setupMap() {
		mapView.computeScroll();
		mapView.setBuiltInZoomControls(true);
		mapController = mapView.getController();
		overlays = mapView.getOverlays();
		
		// Add the current location marker
		locOverlay = new MyLocationOverlay(this, mapView);
		locOverlay.enableCompass();
		locOverlay.enableMyLocation();
		locOverlay.runOnFirstFix(new Runnable() {
			public void run() {
				mapController.animateTo(locOverlay.getMyLocation());
			}
		});
		overlays.add(locOverlay);
	}
	
    /**
     * Initializes data collection procedures. Starts collections location, cell signal, and wifi
     * signal information. Each listener / data collector stores said data in the application
     * SQLite database.
     */
    private void setupBackgroundProcesses() {
    	mapPlotter = new MapPlotterTask(context);
    	mapPlotter.execute(new Void[]{ });
    	
        serverSyncer = new ServerSyncerTask(context);
        serverSyncer.execute(new Void[]{ });
        
        locManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 5000, 10, locListener);
        teleManager.listen(psListener, PhoneStateListener.LISTEN_SIGNAL_STRENGTH);
        
        wifiTracker = new WifiSignalTrackerTask(context, wifiManager, wifiText);
        wifiTracker.execute(new Void[]{ });
    }
	
	/**
	 * Zooms to the current location, if one exists.
	 * @param view the current view, supplied by the system
	 */
	public void zoomToLoc(View view) {
		GeoPoint currentLoc = locOverlay.getMyLocation();
		if (currentLoc != null) {
			mapController.animateTo(currentLoc);
			mapController.setZoom(17);
		} else {
			Utils.toast(this, "No location found. Please make sure your GPS is activated.");
		}
	}

	private void swapViews(MenuItem selected) {
		dataView = (LinearLayout) findViewById(R.id.data_view);
		if (dataView.getVisibility() == LinearLayout.VISIBLE) {
			dataView.setVisibility(LinearLayout.GONE);
			mapView.setVisibility(MapView.VISIBLE);
			zoomToBtn.setVisibility(ImageButton.VISIBLE);
			selected.setTitle(R.string.view_data);
		} else {
			dataView.setVisibility(LinearLayout.VISIBLE);
			mapView.setVisibility(MapView.GONE);
			zoomToBtn.setVisibility(ImageButton.GONE);
			selected.setTitle(R.string.view_map);
		}
	}
	
    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        if(keyCode == KeyEvent.KEYCODE_BACK) {
            Utils.displayQuitDialog(this);
            return true;
        } else {
            return super.onKeyDown(keyCode, event);
        }
    }
}
